package at.fhj.itm;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;

// ----------------------------------------------------------------------

public class CameraPreview extends Activity {
	private Preview mPreview;
	Camera mCamera;
	private Camera.PictureCallback _jpgCallback;
	private SurfaceView mSurfaceView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Hide the window title.
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.camera);
		mSurfaceView = (SurfaceView) findViewById(R.id.cameraSurface);
		// Create our Preview view and set it as the content of our activity.
		mPreview = new Preview(this);
		setContentView(mPreview);

		Log.i("SurfaceView:", mSurfaceView.toString());

		// addCameraCallbacks();
		_jpgCallback = new Camera.PictureCallback() {

			@Override
			public void onPictureTaken(byte[] data, Camera camera) {
				// TODO Redirect to DECODE!!!!
				FileOutputStream outStream = null;
				try {
					outStream = new FileOutputStream(
							String.format("/sdcard/IMG_tmp.png"));

					outStream.write(data);
					outStream.close();

					Log.i("Decode-Camera", "Decoding taken Picture");

					String filePath = Environment.getExternalStorageDirectory()
							.toString() + "/IMG_tmp.png";
					QRDecoder qrd = new QRDecoder();
					qrd.execute(filePath);

					Log.d("Camera-INFO:", "onPictureTaken - wrote bytes: "
							+ data.length);

					startActivity(new Intent(getApplicationContext(),
							QRCodeDecode.class));

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
				}
				Log.d("Camera-INFO:", "onPictureTaken - jpeg");
			}
		};

	}

	/* (non-Javadoc)
	 * @see android.view.View.OnKeyListener#onKey(android.view.View, int, android.view.KeyEvent)
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		Log.d("KeyEvent", "Key event code "+keyCode);
		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_CAMERA) {
			Log.i("KeyPressed","Take Picture");
			mPreview.mCamera.takePicture(null, null, _jpgCallback);
		}
		Log.i("KeyPressed","Wrong Key");
		return false;
	}
	
	
	private void addCameraCallbacks() {
		// picture callback - jpg image
		// _jpgCallback = new Camera.PictureCallback() {
		//
		// @Override
		// public void onPictureTaken(byte[] data, Camera camera) {
		// // TODO Redirect to DECODE!!!!
		// FileOutputStream outStream = null;
		// try {
		// outStream = new FileOutputStream(
		// String.format("/sdcard/IMG_tmp.png"));
		//
		// outStream.write(data);
		// outStream.close();
		//
		// Log.i("Decode-Camera", "Decoding taken Picture");
		//
		// String filePath = Environment.getExternalStorageDirectory()
		// .toString() + "/IMG_tmp.png";
		// QRDecoder qrd = new QRDecoder();
		// qrd.execute(filePath);
		//
		// Log.d("Camera-INFO:", "onPictureTaken - wrote bytes: "
		// + data.length);
		//
		// startActivity(new Intent(getApplicationContext(),
		// QRCodeDecode.class));
		//
		// } catch (FileNotFoundException e) {
		// e.printStackTrace();
		// } catch (IOException e) {
		// e.printStackTrace();
		// } finally {
		// }
		// Log.d("Camera-INFO:", "onPictureTaken - jpeg");
		// }
		// };

		// mSurfaceView.setOnClickListener(new OnClickListener() {
		// public void onClick(View v) {
		// mCamera.takePicture(null, _jpgCallback, _jpgCallback);
		// }
		// });

	}
}

// ----------------------------------------------------------------------

class Preview extends SurfaceView implements SurfaceHolder.Callback {
	SurfaceHolder mHolder;
	Camera mCamera;

	Preview(Context context) {
		super(context);

		// Install a SurfaceHolder.Callback so we get notified when the
		// underlying surface is created and destroyed.
		mHolder = getHolder();
		mHolder.addCallback(this);
		mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	public void surfaceCreated(SurfaceHolder holder) {
		// The Surface has been created, acquire the camera and tell it where
		// to draw.
		mCamera = Camera.open();
		try {
			mCamera.setPreviewDisplay(holder);
		} catch (IOException exception) {
			mCamera.release();
			mCamera = null;
			// TODO: add more exception handling logic here
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// Surface will be destroyed when we return, so stop the preview.
		// Because the CameraDevice object is not a shared resource, it's very
		// important to release it when the activity is paused.
		mCamera.stopPreview();
		mCamera.release();
		mCamera = null;
	}

	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
		final double ASPECT_TOLERANCE = 0.05;
		double targetRatio = (double) w / h;
		if (sizes == null)
			return null;

		Size optimalSize = null;
		double minDiff = Double.MAX_VALUE;

		int targetHeight = h;

		// Try to find an size match aspect ratio and size
		for (Size size : sizes) {
			double ratio = (double) size.width / size.height;
			if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
				continue;
			if (Math.abs(size.height - targetHeight) < minDiff) {
				optimalSize = size;
				minDiff = Math.abs(size.height - targetHeight);
			}
		}

		// Cannot find the one match the aspect ratio, ignore the requirement
		if (optimalSize == null) {
			minDiff = Double.MAX_VALUE;
			for (Size size : sizes) {
				if (Math.abs(size.height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.abs(size.height - targetHeight);
				}
			}
		}
		return optimalSize;
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
		// Now that the size is known, set up the camera parameters and begin
		// the preview.
		Camera.Parameters parameters = mCamera.getParameters();

		List<Size> sizes = parameters.getSupportedPreviewSizes();
		Size optimalSize = getOptimalPreviewSize(sizes, w, h);
		parameters.setPreviewSize(optimalSize.width, optimalSize.height);

		mCamera.setParameters(parameters);
		mCamera.startPreview();
	}

}
